import 'package:inmotion_pro/http/api_type.dart';
import 'package:inmotion_pro/l10n/local.dart';
import 'package:inmotion_pro/pages/mixin/cache_mixin.dart';
import 'package:inmotion_pro/routes/app_routes.dart';
import 'package:inmotion_pro/service/global_service.dart';
import 'package:inmotion_pro/service/log_service.dart';
import 'package:dio/dio.dart' as dio;
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:lx_widgets_library/alert/loading.dart';
import 'package:lx_widgets_library/http/dio_interceptor.dart';

import '../service/translation_service.dart';

// 自定义HTTP拦截器
class ApiInterceptor extends DioInterceptor with CacheMixin {
  // 请求拦截
  @override
  Future<dio.RequestOptions> handleRequest(dio.RequestOptions options) {
    // 在这里可以添加token等请求头
    String token = GlobalService.to.cacheUserInfo.value.token;
    String xAuth = GlobalService.to.cacheUserInfo.value.xAuth;
    if (token.isNotEmpty && xAuth.isNotEmpty) {
      options.headers['Authorization'] = 'Bearer $token';
      options.headers['X-Auth'] = xAuth;
      // 针对v1接口，依旧使用旧的baseUrl
      if (options.path.contains('/v1/')) {
        options.baseUrl = "https://api.net.imscv.com";
      }
    }
    options.headers['Accept-Language'] =
        TranslationService.getLocale().toLanguageTag();
    return super.handleRequest(options);
  }

  // 响应拦截
  @override
  Future<dio.Response> handleResponse(dio.Response response) {
    final rsp = _transform(response);
    if (rsp.apiErrorType != ApiErrorType.success) {
      LogService.to.error('Http异常: ${rsp.apiErrorType.code} - ${rsp.message}');
      switch (rsp.apiErrorType) {
        case ApiErrorType.unauthenticatedRequest:
          // token失效，重新登录
          mixinRemoveCacheRefreshToken().then((rsp) {
            if (rsp) {
              Get.offAllNamed(AppRoutes.LOGIN_REGISTER);
              debugPrint("跳转到登录页面");
            }
          });
        default:
          break;
      }
    }
    // 由于CustomResponse中的字段为code，而当前Api无该字段，且code=0为成功
    // 所以response.data保持原有响应结构，新增code字段
    response.data['code'] = rsp.apiErrorType.code == ApiErrorType.success.code
        ? 0
        : rsp.apiErrorType.code;
    response.data['message'] = rsp.message;
    return super.handleResponse(response);
  }

  // 错误拦截
  @override
  Future<dio.DioException> handleError(dio.DioException err) async {
    if (err.response == null) {
      LogService.to.error('Http错误: ${_fullUrl(err)} - ${err.type}');
    } else {
      LogService.to.error(
          'Http错误: ${_fullUrl(err)} - ${err.response?.statusCode} - ${err.response?.data.toString()}');
    }
    return super.handleError(await _customError(err));
  }

  // 转换响应
  ({ApiErrorType apiErrorType, String message}) _transform(
      dio.Response response) {
    final json = response.data as Map<String, dynamic>;
    int code = json['error'] ?? 0;
    ApiErrorType apiErrorType = ApiErrorType.values.firstWhere(
        (e) => e.code == code,
        orElse: () => ApiErrorType.unknownType);
    String msg = json['message'];
    String message = msg.isNotEmpty ? msg : apiErrorType.message;
    return (apiErrorType: apiErrorType, message: message);
  }

  /// 处理Dio错误
  Future<dio.DioException> _customError(dio.DioException err) {
    final response = err.response;
    if (response == null) {
      Loading.showToast(_getMessageForDioErrorType(err.type));
      return Future.value(err);
    }
    final statusCode = response.statusCode;
    final errorData = response.data;

    // 根据响应数据处理错误
    if (errorData is Map && errorData['message'] != null) {
      final rsp = _transform(response);

      // 处理特定错误代码
      switch (rsp.apiErrorType) {
        case ApiErrorType.unauthenticatedRequest:
          LogService.to
              .error('Http错误 _customError: ${_fullUrl(err)} - ${err.type}');
          return Future.value(err);
        default:
          Loading.showToast(rsp.message);
          return Future.value(err);
      }
    } else {
      String message = _getMessageForStatusCode(statusCode);
      Loading.showToast(message);
      return Future.value(err);
    }
  }

  // 重试请求
  Future<dio.DioException> _retryRequest(
      dio.DioException err, int maxRetryAttempts) {
    final requestOptions = err.requestOptions;
    final retryCount = (requestOptions.extra['retryCount'] ?? 0);

    if (retryCount < maxRetryAttempts) {
      // 更新重试计数
      requestOptions.extra['retryCount'] = retryCount + 1;

      // 延迟后重试
      return Future.delayed(const Duration(milliseconds: 500)).then((_) {
        // 创建新的 Dio 实例以避免拦截器循环
        final dioObj = dio.Dio();

        // 更新headers
        requestOptions.headers['Authorization'] =
            'Bearer ${GlobalService.to.cacheUserInfo.value.token}';

        // 复制原始请求的选项
        final options = dio.Options(
          method: requestOptions.method,
          headers: requestOptions.headers,
          extra: requestOptions.extra,
          responseType: requestOptions.responseType,
        );

        // 重试请求
        return dioObj
            .request(_fullUrl(err),
                data: requestOptions.data,
                queryParameters: requestOptions.queryParameters,
                options: options,
                cancelToken: requestOptions.cancelToken,
                onSendProgress: requestOptions.onSendProgress,
                onReceiveProgress: requestOptions.onReceiveProgress)
            .then((response) {
          return dio.DioException(
            requestOptions: requestOptions,
            response: response,
            type: dio.DioExceptionType.badResponse,
          );
        });
      });
    } else {
      // 不满足重试条件或达到最大重试次数，返回原始错误
      return Future.value(err);
    }
  }

  // 确保使用完整 URL
  String _fullUrl(dio.DioException err) {
    final requestOptions = err.requestOptions;
    return requestOptions.uri.isAbsolute
        ? requestOptions.uri.toString()
        : '${requestOptions.baseUrl}${requestOptions.path}';
  }

  /// 根据HTTP状态码获取错误信息
  String _getMessageForStatusCode(int? statusCode) {
    switch (statusCode) {
      case 400:
        return local.param_error;
      case 401:
        return local.auth_error;
      case 403:
        return local.permission_error;
      case 404:
        return local.resource_not_found_error;
      case 500:
        return local.server_internal_error;
      default:
        return "${local.unknown_error} HTTP-$statusCode";
    }
  }

  /// 根据DioErrorType获取错误信息
  String _getMessageForDioErrorType(dio.DioExceptionType type) {
    switch (type) {
      case dio.DioExceptionType.connectionTimeout:
        return local.request_timeout;
      case dio.DioExceptionType.sendTimeout:
        return local.send_timeout;
      case dio.DioExceptionType.receiveTimeout:
        return local.receive_timeout;
      case dio.DioExceptionType.cancel:
        return local.request_cancel;
      default:
        return local.network_error;
    }
  }
}
